package com.tianji.learning.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.course.*;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.QuestionAdminPageQuery;
import com.tianji.learning.domain.dto.QuestionFormDTO;
import com.tianji.learning.domain.dto.QuestionPageQuery;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.vo.QuestionAdminVO;
import com.tianji.learning.domain.vo.QuestionVO;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.learning.service.IInteractionReplyService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动提问的问题表 服务实现类
 * </p>
 *
 * @author WFan
 * @since 2025-03-27
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements IInteractionQuestionService {

    private final IInteractionReplyService interactionReplyService;

    private final CatalogueClient catalogueClient;

    private final CategoryCache categoryCache;

    private final CourseClient courseClient;

    private final SearchClient searchClient;

    private final UserClient userClient;


    /**
     * 新增互动问题
     *
     * @param questionDTO
     */
    @Override
    public void saveQuestion(QuestionFormDTO questionDTO) {
        // 1.参数校验
        if (ObjectUtil.isEmpty(questionDTO)) {
            throw new BadRequestException("参数不能为空");
        }

        // 2.拷贝数据至实体对象
        InteractionQuestion interactionQuestion = BeanUtil.toBean(questionDTO, InteractionQuestion.class);

        // 3.填充userId
        interactionQuestion.setUserId(UserContext.getUser());

        // 4.保存数据
        this.save(interactionQuestion);
        log.info("保存问题成功，问题id为：{}", interactionQuestion.getId());

    }

    /**
     * 用户端分页查询互动问题
     *
     * @param pageQuery
     * @return
     */
    @Override
    public PageDTO<QuestionVO> queryQuestionPage(QuestionPageQuery pageQuery) {
        // 1.参数校验
        if (ObjectUtil.isEmpty(pageQuery.getCourseId()) && ObjectUtil.isEmpty(pageQuery.getSectionId())) {
            throw new BadRequestException("课程id与小节id不能为空");
        }

        // 2.分页查询问题表
        Page<InteractionQuestion> questionPage = this.lambdaQuery().eq(ObjectUtil.isNotEmpty(pageQuery.getCourseId()), InteractionQuestion::getCourseId, pageQuery.getCourseId())
                .eq(ObjectUtil.isNotEmpty(pageQuery.getSectionId()), InteractionQuestion::getSectionId, pageQuery.getSectionId())
                .eq(pageQuery.getOnlyMine(), InteractionQuestion::getUserId, UserContext.getUser())
                .eq(InteractionQuestion::getHidden, false)
                .page(pageQuery.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionQuestion> records = questionPage.getRecords();
        if (ObjectUtil.isEmpty(records)) {
            return PageDTO.empty(questionPage);
        }

        // 3.查询出所有非匿名提问用户id，查询出所有最新回答的id
        Set<Long> userIds = new HashSet<>();
        Set<Long> latestAnswerIds = new HashSet<>();
        for (InteractionQuestion record : records) {
            if (!record.getAnonymity()) {
                // 如果不是匿名问题，则需要查询出用户信息
                userIds.add(record.getUserId());
            }
            if (ObjectUtil.isNotEmpty(record.getLatestAnswerId())) {
                // 如果有最新回答，则需要查询出最新回答的id
                latestAnswerIds.add(record.getLatestAnswerId());
            }
        }

        // 4.根据latestAnswerIds查询最新回答
        List<InteractionReply> replies = null;
        if (ObjectUtil.isNotEmpty(latestAnswerIds)) {
            replies = interactionReplyService.lambdaQuery()
                    .in(InteractionReply::getId, latestAnswerIds)
                    .eq(InteractionReply::getHidden, false)
                    .list();
        }
        Map<Long, InteractionReply> replyMap = new HashMap<>(replies.size());
        if (ObjectUtil.isNotEmpty(replies)) {
            replyMap = replies.stream().collect(Collectors.toMap(InteractionReply::getId, r -> r));
        }

        // 5.添加非匿名回答者的userId
        if (ObjectUtil.isNotEmpty(replies)) {
            for (InteractionReply reply : replies) {
                if (!reply.getAnonymity()) {
                    userIds.add(reply.getUserId());
                }
            }
        }

        // 6.根据userIds查询出用户信息
        List<UserDTO> usersInfo = userClient.queryUserByIds(userIds);
        Map<Long, UserDTO> userDTOMap = usersInfo.stream().collect(Collectors.toMap(UserDTO::getId, r -> r));

        // 7.填充数据组装vo
        List<QuestionVO> questionVOS = new ArrayList<>(records.size());
        for (InteractionQuestion record : records) {
            QuestionVO vo = BeanUtil.toBean(record, QuestionVO.class);
            if (!record.getAnonymity()) {
                // 如果不是匿名问题，则需填充用户信息
                vo.setUserName(userDTOMap.get(record.getUserId()).getName());
                vo.setUserIcon(userDTOMap.get(record.getUserId()).getIcon());
            }
            if (ObjectUtil.isNotEmpty(record.getLatestAnswerId()) && ObjectUtil.isNotEmpty(replyMap)) {
                // 如果有最新回答，则需要填充最新回答信息
                vo.setLatestReplyContent(replyMap.get(record.getLatestAnswerId()).getContent());
                if (!replyMap.get(record.getLatestAnswerId()).getAnonymity()) {
                    vo.setLatestReplyUser(userDTOMap.get(replyMap.get(record.getLatestAnswerId()).getUserId()).getName());
                }
            }
            questionVOS.add(vo);
        }

        return PageDTO.of(questionPage, questionVOS);
    }

    /**
     * 编辑互动问题
     *
     * @param questionDTO
     */
    @Override
    public void updateQuestion(QuestionFormDTO questionDTO, Long id) {
        // 1.参数校验
        if (ObjectUtil.isEmpty(questionDTO)) {
            throw new BadRequestException("参数不能为空");
        }

        // 2.修改数据库
        boolean update = this.lambdaUpdate().eq(InteractionQuestion::getId, id)
                .eq(InteractionQuestion::getUserId, UserContext.getUser())
                .set(ObjectUtil.isNotEmpty(questionDTO.getTitle()), InteractionQuestion::getTitle, questionDTO.getTitle())
                .set(ObjectUtil.isNotEmpty(questionDTO.getDescription()), InteractionQuestion::getDescription, questionDTO.getDescription())
                .set(ObjectUtil.isNotEmpty(questionDTO.getAnonymity()), InteractionQuestion::getAnonymity, questionDTO.getAnonymity())
                .update();
        log.info(update ? "修改成功" : "修改失败");
    }

    /**
     * 根据id查询问题详情
     *
     * @param id
     * @return
     */
    @Override
    public QuestionVO getQuestionById(Long id) {
        // 1.查询数据库
        InteractionQuestion question = this.getById(id);
        if (ObjectUtil.isEmpty(question)) {
            throw new BadRequestException("问题不存在");
        }

        QuestionVO vo = BeanUtil.toBean(question, QuestionVO.class);

        // 2.如果不是匿名，查询用户信息
        if (!question.getAnonymity()) {
            UserDTO userInfo = userClient.queryUserById(question.getUserId());
            if (ObjectUtil.isEmpty(userInfo)) {
                log.info("未查询到该用户");
            } else {
                vo.setUserName(userInfo.getName());
                vo.setUserIcon(userInfo.getIcon());
            }
        }
        return vo;
    }

    /**
     * 根据id删除问题
     *
     * @param id
     */
    @Override
    @Transactional
    public void removeByIdAndUserId(Long id) {
        // 1.查询数据库
        InteractionQuestion question = this.getById(id);
        if (ObjectUtil.isEmpty(question)) {
            throw new BadRequestException("问题不存在");
        }

        // 2.判断该问题是否属于当前用户
        if (!question.getUserId().equals(UserContext.getUser())) {
            log.info("该问题不属于当前用户");
            return;
        }

        // 3.删除问题下的回答
        interactionReplyService.lambdaUpdate()
                .eq(InteractionReply::getQuestionId, id)
                .remove();

        // 4.删除问题
        boolean b = this.removeById(id);
        log.info(b ? "删除成功" : "删除失败");
    }

    /**
     * 管理端分页查询问题
     *
     * @param pageQuery
     * @return
     */
    @Override
    public PageDTO<QuestionAdminVO> queryQuestionPageOfAdmin(QuestionAdminPageQuery pageQuery) {
        // 1.根据课程名称查询课程id集合
        List<Long> coursesIds = new ArrayList<>();
        if (ObjectUtil.isNotEmpty(pageQuery.getCourseName())) {
            coursesIds = searchClient.queryCoursesIdByName(pageQuery.getCourseName());
        }

        // 2.根据课程id集合问题分页查询
        Page<InteractionQuestion> page = this.lambdaQuery()
                .eq(ObjectUtil.isNotEmpty(pageQuery.getStatus()), InteractionQuestion::getStatus, pageQuery.getStatus())
                .in(ObjectUtil.isNotEmpty(coursesIds), InteractionQuestion::getCourseId, coursesIds)
                .ge(ObjectUtil.isNotEmpty(pageQuery.getBeginTime()), InteractionQuestion::getCreateTime, pageQuery.getBeginTime())
                .le(ObjectUtil.isNotEmpty(pageQuery.getEndTime()), InteractionQuestion::getCreateTime, pageQuery.getEndTime())
                .page(pageQuery.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionQuestion> records = page.getRecords();

        if (ObjectUtil.isEmpty(records)) {
            return PageDTO.empty(page);
        }

        // 3.获取小节id加章节id集合，获取课程id集合,获取用户id结合，
        Set<Long> userIds = new HashSet<>(records.size());
        Set<Long> sectionIds = new HashSet<>(records.size());
        Set<Long> courseIds = new HashSet<>(records.size());
        for (InteractionQuestion record : records) {
            sectionIds.add(record.getSectionId());
            sectionIds.add(record.getChapterId());
            courseIds.add(record.getCourseId());
            userIds.add(record.getUserId());


        }

        // 3.根据小节id 查询课程目录信息，获取章节名称-小节名称
        List<CataSimpleInfoDTO> cataSimpleInfoDTOS = catalogueClient.batchQueryCatalogue(sectionIds);
        // 章节名称map集合 章节/小节id - 名称
        Map<Long, String> cataNameMap = cataSimpleInfoDTOS.stream()
                .collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));

        // 4.根据课程id查询课程信息，获取课程名称，分类名称
        List<CourseSimpleInfoDTO> corseInfoList = courseClient.getSimpleInfoList(courseIds);
        // 课程信息Map集合 课程id - 课程信息
        Map<Long, CourseSimpleInfoDTO> courseInforMap = new HashMap<>(corseInfoList.size());
        // 获取分类id集合 课程id - 分类id集合
        Map<Long, List<Long>> cateIds = new HashMap<>(corseInfoList.size());
        if (ObjectUtil.isNotEmpty(corseInfoList)) {
            for (CourseSimpleInfoDTO courseSimpleInfo : corseInfoList) {
                courseInforMap.put(courseSimpleInfo.getId(), courseSimpleInfo);
                cateIds.put(courseSimpleInfo.getId(), courseSimpleInfo.getCategoryIds());
            }
        }

        // 5.获取用户信息Map 集合
        Map<Long, String> userInfo = userClient.queryUserByIds(userIds).stream().collect(Collectors.toMap(UserDTO::getId, UserDTO::getName));

        // 6.封装数据
        List<QuestionAdminVO> vos = new ArrayList<>(records.size());
        for (InteractionQuestion record : records) {
            if (ObjectUtil.isNotEmpty(record)) {
                QuestionAdminVO vo = BeanUtil.toBean(record, QuestionAdminVO.class);
                vo.setChapterName(cataNameMap.get(record.getChapterId()));
                vo.setSectionName(cataNameMap.get(record.getSectionId()));
                vo.setCourseName(courseInforMap.get(record.getCourseId()).getName());
                vo.setCategoryName(categoryCache.getCategoryNames(cateIds.get(record.getCourseId())));
                vo.setUserName(userInfo.get(record.getUserId()));
                vos.add(vo);
            }
        }
        return PageDTO.of(page, vos);
    }

    /**
     * 管理端修改问题隐藏状态
     *
     * @param id
     * @param hidden
     */
    @Override
    public void updateHidden(Long id, Boolean hidden) {
        this.lambdaUpdate().eq(InteractionQuestion::getId, id)
                .set(InteractionQuestion::getHidden, hidden)
                .update();
    }

    /**
     * 管理端查询互动问题详情
     *
     * @param id
     * @return
     */
    @Override
    public QuestionAdminVO getQuestionInfoById(Long id) {
        // 1.查询问题详情
        InteractionQuestion question = this.getById(id);
        if (ObjectUtil.isEmpty(question)) {
            throw new BadRequestException("问题不存在");
        }
        QuestionAdminVO vo = BeanUtil.toBean(question, QuestionAdminVO.class);

        Set<Long> userIds = new HashSet<>();
        List<Long> teacherIds = new ArrayList<>();
        // 2.查询课程信息
        CourseFullInfoDTO courseInfo = courseClient.getCourseInfoById(question.getCourseId(), true, true);
        if (ObjectUtil.isNotEmpty(courseInfo)) {
            // 获取教师id，添加到集合
            teacherIds = courseInfo.getTeacherIds();
            for (Long teacherId : teacherIds) {
                userIds.add(teacherId);
            }

            // 获取分类id集合
            List<Long> cateIds = courseInfo.getCategoryIds();
            // 填充三级分类名称
            vo.setCategoryName(categoryCache.getCategoryNames(cateIds));
            // 填充课程名称
            vo.setCourseName(courseInfo.getName());
        }

        // 3.查询用户信息、老师信息
        userIds.add(question.getUserId());
        Map<Long, UserDTO> userInfos = userClient.queryUserByIds(userIds).stream().collect(Collectors.toMap(UserDTO::getId, Function.identity()));

        // 4.查询目录信息
        List<Long> cataIds = new ArrayList<>(2);
        cataIds.add(question.getChapterId());
        cataIds.add(question.getSectionId());
        Map<Long, String> cataNames = catalogueClient.batchQueryCatalogue(cataIds).stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));


        // 6.封装数据
        if (ObjectUtil.isNotEmpty(cataNames)) {
            vo.setChapterName(cataNames.get(question.getChapterId()));
            vo.setSectionName(cataNames.get(question.getSectionId()));
        }
        if (ObjectUtil.isNotEmpty(userInfos)) {
            vo.setUserName(userInfos.get(question.getUserId()).getName());
            vo.setUserIcon(userInfos.get(question.getUserId()).getIcon());
            List<String> teacherName = new ArrayList<>(teacherIds.size());
            for (Long teacherId : teacherIds) {
                teacherName.add(userInfos.get(teacherId).getName());
            }
            vo.setTeacherName(StrUtil.join(",", teacherName));
        }
        return vo;
    }


}
